package com.wlcb.jpower.utils;

import com.wlcb.jpower.constant.RedisEunm;
import com.wlcb.jpower.module.common.redis.RedisUtil;
import com.wlcb.jpower.module.common.utils.SpringUtil;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.ScanOptions;

import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

/**
 * @description:
 * @author: liwenfei
 * @time: 2021/1/19 10:38
 */
public class RedisHelpUtils {

    private static RedisUtil redisUtil;

    private static RedissonClient redissonClient;

    static {
        redissonClient = SpringUtil.getBean(RedissonClient.class);
        redisUtil = SpringUtil.getBean(RedisUtil.class);
    }

    public static RedisUtil getRedisUtil() {
        return redisUtil;
    }

    /**
     * scan 实现
     *
     * @param pattern  表达式
     * @param consumer 对迭代到的key进行操作
     */
    public static void scan(String pattern, Consumer<byte[]> consumer) {
        redisUtil.getRedisTemplate().execute((RedisConnection connection) -> {
            try (Cursor<byte[]> cursor = connection.scan(ScanOptions.scanOptions().count(1000).match(pattern).build())) {
                cursor.forEachRemaining(consumer);
                return null;
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException(e);
            }
        });
    }

    /**
     * redis锁
     *
     * @return
     */
    public static RedisLock getRedisLock() {
        return new RedisLock();
    }


    public static class RedisLock {

        public RLock rlock(String lockKey) {
            RLock lock = redissonClient.getLock(RedisEunm.LOCK.getKeyPrefix() + lockKey);
            lock.lock();
            return lock;
        }

        /**
         * @param lockKey   锁
         * @param unit      释放时间单位
         * @param waitTime  等待锁的最大时间，超过时间不再尝试获取所。
         * @param leaseTime 如果没有手动调用unlock，超过时间自动释放
         * @return
         */
        public boolean tryLock(String lockKey, TimeUnit unit, int waitTime, int leaseTime) {
            RLock lock = redissonClient.getLock(RedisEunm.LOCK.getKeyPrefix() + lockKey);
            try {
                return lock.tryLock(waitTime, leaseTime, unit);
            } catch (InterruptedException e) {
                return false;
            }
        }

        public boolean tryLock(String lockKey) {
            RLock lock = redissonClient.getLock(RedisEunm.LOCK.getKeyPrefix() + lockKey);
            return lock.tryLock();
        }

        public void runlock(String lockKey) {
            RLock lock = redissonClient.getLock(RedisEunm.LOCK.getKeyPrefix() + lockKey);
            lock.unlock();
        }

        public void runlock(RLock lock) {
            lock.unlock();
        }
    }
}
